﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YJKArchUtils.Utils;
using YJKRevitDimensionText.OneKeyPlanDim.Utility;

namespace YJKRevitDimensionText.OneKeyPlanDim.DimData
{
	public class DbCarRamp : DbDimBase
	{
		public DbCarRamp(Floor floor1, Floor floor2)
		{
			this.m_floor1 = floor1;
			this.m_floor2 = floor2;
		}

		public List<Curve> CenterLineList
		{
			get
			{
				this.AnalysisInfo();
				return this.m_CenterLineList;
			}
		}

		public override bool CreateSizeDim(Autodesk.Revit.DB.Document doc)
		{
			if (!base.CreateSizeDim(doc))
			{
				return false;
			}
			if (!this.AnalysisInfo())
			{
				return false;
			}
			if (this.m_lstCarBasePlanarFace1.Count == 0 || this.m_lstCarBasePlanarFace1.Count != this.m_lstCarBasePlanarFace2.Count)
			{
				return false;
			}
			Grid grid = null;
			DbAxial dbAxial = null;
			if (base.GetDbAxialWithDir(this.m_lstCarBasePlanarFace1[0].SlopeDir, out dbAxial))
			{
				double num = 0.0;
				grid = dbAxial.GetGridNearestXZY(this.m_lstCarBasePlanarFace1[0].OutPoint, ref num);
				double num2 = 0.0;
				Grid gridNearestXZY = dbAxial.GetGridNearestXZY(this.m_lstCarBasePlanarFace2[0].OutPoint, ref num2);
				if (Geometry.LessThan(num2, num))
				{
					grid = gridNearestXZY;
				}
				if (Geometry.IsEqual(num, 0.0) || Geometry.IsEqual(num2, 0.0))
				{
					grid = null;
				}
			}
			DetailCurve detailCurveWithPoint = CommonInterface.GetDetailCurveWithPoint(this.m_doc, this.m_lstCarBasePlanarFace1[0].OutPoint, this.m_lstCarBasePlanarFace1[0].SlopeDir);
			DetailCurve detailCurveWithPoint2 = CommonInterface.GetDetailCurveWithPoint(this.m_doc, this.m_lstCarBasePlanarFace2[0].OutPoint, this.m_lstCarBasePlanarFace1[0].SlopeDir);
			ReferenceArray referenceArray = new ReferenceArray();
			if (detailCurveWithPoint != null)
			{
				Reference reference = new Reference(detailCurveWithPoint);
				referenceArray.Append(reference);
			}
			if (detailCurveWithPoint2 != null)
			{
				Reference reference = new Reference(detailCurveWithPoint2);
				referenceArray.Append(reference);
			}
			if (grid != null)
			{
				XYZ xyz = (grid.Curve as Line).Project(this.m_lstCarBasePlanarFace1[0].OutPoint).XYZPoint;
				xyz = new XYZ(xyz.X, xyz.Y, this.m_lstCarBasePlanarFace1[0].OutPoint.Z);
				DetailCurve detailCurveWithPoint3 = CommonInterface.GetDetailCurveWithPoint(this.m_doc, xyz, this.m_lstCarBasePlanarFace1[0].SlopeDir);
				if (detailCurveWithPoint3 != null)
				{
					Reference reference = new Reference(detailCurveWithPoint3);
					referenceArray.Append(reference);
				}
			}
			XYZ dir = -this.m_lstCarBasePlanarFace1[0].SlopeDir;
			Line line = Line.CreateUnbound(this.m_lstCarBasePlanarFace1[0].OutPoint, this.m_lstCarBasePlanarFace1[0].OutPoint - this.m_lstCarBasePlanarFace2[0].OutPoint);
			double dLength = Common.MMToFeet((double)(2000 * (this.m_doc.ActiveView.Scale / 100)));
			line = CommonInterface.NextDodgeLine(line, dir, dLength);
			Dimension dimension = new SizeDimData(this.m_doc, line, referenceArray).CreateDim(true);
			if (dimension == null)
			{
				return false;
			}
			this.SetDimPosition(dimension, line, dir);
			return true;
		}

		public override bool CreateLevelDim(Autodesk.Revit.DB.Document doc, out List<SingleLevelDimDataInfo> lstSingleLevelDimDataInfo)
		{
			if (!base.CreateLevelDim(doc, out lstSingleLevelDimDataInfo))
			{
				return false;
			}
			if (!this.AnalysisInfo())
			{
				return false;
			}
			if (this.m_lstCarBasePlanarFace1.Count == 0 || this.m_lstCarBasePlanarFace2.Count == 0)
			{
				return false;
			}
			XYZ xyz = (this.m_lstCarBasePlanarFace1[0].InPoint + this.m_lstCarBasePlanarFace2[0].InPoint) / 2.0 - this.m_lstCarBasePlanarFace1[0].SlopeDir * (Common.MMToFeet(1500.0) * (double)this.m_doc.ActiveView.Scale / 100.0);
			if (base.ComponentInSlopePlanarFace != null)
			{
				xyz = CommonInterface.PtInPlanarFaceInDir(xyz, base.ComponentInSlopePlanarFace, XYZ.BasisZ);
			}
			FamilyInstance familyInstance = new LevelDimData(this.m_doc)
			{
				PtDimLocation = xyz,
				DimVal = base.FloorLevelVal
			}.CreateLevelDim();
			AnnotationSymbol annotationSymbol = null;
			if (familyInstance != null)
			{
				annotationSymbol = (familyInstance as AnnotationSymbol);
			}
			if (annotationSymbol != null)
			{
				SingleLevelDimDataInfo singleLevelDimDataInfo = new SingleLevelDimDataInfo(annotationSymbol);
				if (base.ComponentInSlopePlanarFace != null)
				{
					singleLevelDimDataInfo.LevelVal = xyz.Z;
				}
				else
				{
					singleLevelDimDataInfo.LevelVal = base.dFloorLevelVal;
				}
				singleLevelDimDataInfo.LadderLineLength = this.m_lstCarBasePlanarFace1[0].OutPoint.DistanceTo(this.m_lstCarBasePlanarFace2[0].OutPoint);
				singleLevelDimDataInfo.DimDir = this.m_lstCarBasePlanarFace1[0].SlopeDir;
				singleLevelDimDataInfo.PtLocation = xyz;
				singleLevelDimDataInfo.bStepDownDim = false;
				singleLevelDimDataInfo.m_LstElementId.Add(this.m_floor1.Id);
				singleLevelDimDataInfo.m_LstElementId.Add(this.m_floor2.Id);
				lstSingleLevelDimDataInfo.Add(singleLevelDimDataInfo);
			}
			return true;
		}

		public override bool CreateSlopeDim(Autodesk.Revit.DB.Document doc)
		{
			if (!base.CreateSlopeDim(doc))
			{
				return false;
			}
			if (!this.AnalysisInfo())
			{
				return false;
			}
			SlopeDimData slopeDimData = new SlopeDimData(this.m_doc);
			foreach (CarBasePlanarFace carBasePlanarFace in this.m_lstCarBasePlanarFace1)
			{
				if (carBasePlanarFace.IsSlopePlanarFace())
				{
					slopeDimData.PtStart = carBasePlanarFace.InPoint;
					slopeDimData.SlopeDimDir = carBasePlanarFace.SlopeDir;
					slopeDimData.DimVal = carBasePlanarFace.SlopeValue;
					FamilyInstance familyInstance = slopeDimData.CreateSlopeDim();
					if (familyInstance == null)
					{
						return false;
					}
					base.SetSlopeOcclusionArea(familyInstance);
					return true;
				}
			}
			return true;
		}

		public bool AnalysisInfo()
		{
			if (!base.IsNeedAnalysisInfo())
			{
				return true;
			}
			try
			{
				this.m_lstTrackCv = this.GetBottomCenterLineList();
				List<PlanarFace> allPlanarFace = GeometryHelper.GetAllPlanarFace(this.m_floor1);
				List<RuledFace> allRuledFace = GeometryHelper.GetAllRuledFace(this.m_floor1);
				List<Face> list = new List<Face>();
				list.AddRange(allPlanarFace);
				list.AddRange(allRuledFace);
				List<CurveLoop> list2 = new List<CurveLoop>();
				foreach (Curve trackCv in this.m_lstTrackCv)
				{
					foreach (Face face in list)
					{
						CarBasePlanarFace carBasePlanarFace = new CarBasePlanarFace(face);
						carBasePlanarFace.FloorThickness = this.m_dThickNess1;
						if (carBasePlanarFace.IsCarBasePlanarFace(trackCv))
						{
							this.m_lstCarBasePlanarFace1.Add(carBasePlanarFace);
							foreach (CurveLoop curveLoop in carBasePlanarFace.BasePlanarFace.GetEdgesAsCurveLoops())
							{
								CurveLoop xyplaneCurve = CommonInterface.GetXYPlaneCurve(curveLoop);
								list2.Add(xyplaneCurve);
							}
						}
					}
				}
				OcclusionArea.GetInstance().AddRampCurve(this.m_floor1.Id, list2);
				List<PlanarFace> allPlanarFace2 = GeometryHelper.GetAllPlanarFace(this.m_floor2);
				List<RuledFace> allRuledFace2 = GeometryHelper.GetAllRuledFace(this.m_floor2);
				List<Face> list3 = new List<Face>();
				list3.AddRange(allPlanarFace2);
				list3.AddRange(allRuledFace2);
				List<CurveLoop> list4 = new List<CurveLoop>();
				foreach (Curve trackCv2 in this.m_lstTrackCv)
				{
					foreach (Face face2 in list3)
					{
						CarBasePlanarFace carBasePlanarFace2 = new CarBasePlanarFace(face2);
						carBasePlanarFace2.FloorThickness = this.m_dThickNess2;
						if (carBasePlanarFace2.IsCarBasePlanarFace(trackCv2))
						{
							this.m_lstCarBasePlanarFace2.Add(carBasePlanarFace2);
							foreach (CurveLoop curveLoop2 in carBasePlanarFace2.BasePlanarFace.GetEdgesAsCurveLoops())
							{
								list4.Add(CommonInterface.GetXYPlaneCurve(curveLoop2));
							}
						}
					}
				}
				OcclusionArea.GetInstance().AddRampCurve(this.m_floor2.Id, list4);
			}
			catch
			{
				return false;
			}
			return true;
		}

		public bool AnalyserRamp()
		{
			List<Curve> allEdgeList = GeometryHelper.GetAllEdgeList(this.m_floor1);
			if (allEdgeList.Count < 1)
			{
				return false;
			}
			List<Curve> allEdgeList2 = GeometryHelper.GetAllEdgeList(this.m_floor2);
			if (allEdgeList2.Count < 1)
			{
				return false;
			}
			this.m_dThickNess1 = this.FloorThickness(this.m_floor1);
			this.m_dThickNess2 = this.FloorThickness(this.m_floor2);
			foreach (Curve curve in allEdgeList)
			{
				if (!Geometry.IsEqual(curve.Length, this.m_dThickNess1, 0.01))
				{
					XYZ hyendPoint = RevitDocumentExtension.GetEndPoint(curve, 0);
					XYZ hyendPoint2 = RevitDocumentExtension.GetEndPoint(curve, 1);
					foreach (Curve curve2 in allEdgeList2)
					{
						if (!Geometry.IsEqual(curve2.Length, this.m_dThickNess2, 0.01))
						{
							XYZ hyendPoint3 = RevitDocumentExtension.GetEndPoint(curve2, 0);
							XYZ hyendPoint4 = RevitDocumentExtension.GetEndPoint(curve2, 1);
							if ((hyendPoint.IsAlmostEqualTo(hyendPoint3, 0.0001) && hyendPoint2.IsAlmostEqualTo(hyendPoint4, 0.0001)) || (hyendPoint.IsAlmostEqualTo(hyendPoint4, 0.0001) && hyendPoint2.IsAlmostEqualTo(hyendPoint3, 0.0001)))
							{
								this.m_CenterLineList.Add(curve);
							}
						}
					}
				}
			}
			return this.m_CenterLineList.Count > 0;
		}

		private void SetDimPosition(Dimension newDim, Line lineRef, XYZ dir)
		{
			List<CurveLoop> componentAndSizeAndSlopeOcclusionArea = OcclusionArea.GetInstance().GetComponentAndSizeAndSlopeOcclusionArea();
			List<CurveLoop> sizeDimCurveLoop = OcclusionArea.GetSizeDimCurveLoop(newDim);
			XYZ origin = lineRef.Origin;
			XYZ ptEnd = origin;
			List<CurveLoop> list = new List<CurveLoop>();
			for (int i = 0; i < 3; i++)
			{
				ptEnd = CommonInterface.GetNextPositionByOffset(i, Common.MMToFeet(300.0), origin, dir);
				list = CommonInterface.MoveLstCurve(sizeDimCurveLoop, origin, ptEnd);
				bool flag = false;
				using (List<CurveLoop>.Enumerator enumerator = list.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						if (CommonInterface.IsExistOcclusion(enumerator.Current, componentAndSizeAndSlopeOcclusionArea))
						{
							flag = true;
							break;
						}
					}
				}
				if (!flag)
				{
					break;
				}
				if (2 == i)
				{
					ptEnd = origin;
					break;
				}
			}
			OcclusionArea.GetInstance().m_lstSizeDimCvLoop.AddRange(list);
			CommonInterface.MoveElement(newDim, origin, ptEnd, this.m_doc);
		}

		private double FloorThickness(Floor floor)
		{
			if (floor == null)
			{
				return 0.0;
			}
			return floor.GetParameters("厚度").First<Parameter>().AsDouble();
		}

		private List<Curve> GetBottomCenterLineList()
		{
			double num = this.FloorThickness(this.m_floor1);
			List<Curve> list = new List<Curve>();
			double num2 = double.MaxValue;
			Curve curve = null;
			XYZ xyz = null;
			List<Curve> list2 = new List<Curve>();
			for (int i = 0; i < this.m_CenterLineList.Count; i++)
			{
				if (!Geometry.IsEqual(this.m_CenterLineList[i].Length, num, 0.01))
				{
					list2.Add(this.m_CenterLineList[i]);
					if (Geometry.LessThan(this.m_CenterLineList[i].GetEndPoint(0).Z, num2) || Geometry.LessThan(this.m_CenterLineList[i].GetEndPoint(1).Z, num2))
					{
						XYZ endPoint;
						if (Geometry.LessThan(this.m_CenterLineList[i].GetEndPoint(0).Z, this.m_CenterLineList[i].GetEndPoint(1).Z))
						{
							xyz = this.m_CenterLineList[i].GetEndPoint(1);
							endPoint = this.m_CenterLineList[i].GetEndPoint(0);
						}
						else
						{
							xyz = this.m_CenterLineList[i].GetEndPoint(0);
							endPoint = this.m_CenterLineList[i].GetEndPoint(1);
						}
						num2 = endPoint.Z;
						curve = this.m_CenterLineList[i];
					}
				}
			}
			list.Add(curve);
			XYZ xyz2 = xyz * 2.0;
			XYZ ptDown = xyz;
			while (curve != null)
			{
				curve = this.GetOneCurveByBottomPoint(ref list2, ptDown, out xyz2);
				if (curve != null)
				{
					ptDown = xyz2;
					list.Add(curve);
				}
			}
			return list;
		}

		private Curve GetOneCurveByBottomPoint(ref List<Curve> lstCv, XYZ ptDown, out XYZ ptUp)
		{
			ptUp = ptDown;
			for (int i = 0; i < lstCv.Count; i++)
			{
				if (lstCv[i].GetEndPoint(0).IsAlmostEqualTo(ptDown) && Geometry.LessThan(lstCv[i].GetEndPoint(0).Z, lstCv[i].GetEndPoint(1).Z))
				{
					ptUp = lstCv[i].GetEndPoint(1);
					Curve result = lstCv[i];
					lstCv.RemoveAt(i);
					return result;
				}
				if (lstCv[i].GetEndPoint(1).IsAlmostEqualTo(ptDown) && Geometry.LessThan(lstCv[i].GetEndPoint(1).Z, lstCv[i].GetEndPoint(0).Z))
				{
					ptUp = lstCv[i].GetEndPoint(0);
					Curve result2 = lstCv[i];
					lstCv.RemoveAt(i);
					return result2;
				}
			}
			return null;
		}

		private Floor m_floor1;

		private Floor m_floor2;

		private double m_dThickNess1;

		private double m_dThickNess2;

		private List<Curve> m_CenterLineList = new List<Curve>();

		private List<Curve> m_lstTrackCv = new List<Curve>();

		private List<CarBasePlanarFace> m_lstCarBasePlanarFace1 = new List<CarBasePlanarFace>();

		private List<CarBasePlanarFace> m_lstCarBasePlanarFace2 = new List<CarBasePlanarFace>();
	}
}
